home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / sps2 / part01 next >
Encoding:
Internet Message Format  |  1991-01-08  |  52.7 KB

  1. Subject:  v23i047:  SPS, a PS replacement, Part01/04
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 6a92e50e 6b8798bb 3a3131b4 641f24ef
  5.  
  6. Submitted-by: Robert Ward <olsen!robert@uunet.uu.net>
  7. Posting-number: Volume 23, Issue 47
  8. Archive-name: sps2/part01
  9.  
  10. [ I renamed the Makefiles so that SystemV sites would have less trouble.
  11.   --r$ ]
  12.  
  13. Introduction:
  14.     SPS is a intended to be used as a replacement for the standard
  15.     ps(1) program. Its advantages over ps(1) are that it shows more
  16.     useful information, that the displayed information is more
  17.     comprehensible and that it is faster.
  18.  
  19.  
  20.     SPS is currently implemented for the following operating systems and
  21.     architectures.  The corresponding Makefiles are also shown here:
  22.  
  23.     Makefile.4.1        Standard 4.1bsd for Vax
  24.     Makefile.4.2        Standard 4.2bsd, Ultrix 1.x for Vax
  25.     Makefile.4.3        Standard 4.3bsd (or 4.3-tahoe) for Vax
  26.     Makefile.4.3+NFS    4.3bsd+NFS from Wisconsin (Mt. Xinu?, others?)
  27.     Makefile.dec3100    DECStation 3100 + Ultrix 3.0 (incomplete)
  28.     Makefile.sun.2.0    Sun 4.2 UNIX Release 2.0 - 2.2 for Sun-2
  29.     Makefile.sun.3.0    Sun 4.2 UNIX Release 3.0 for Sun-2, Sun-3
  30.     Makefile.sun.3.2    Sun 4.2 UNIX Release 3.2 for Sun-2, Sun-3
  31.     Makefile.sun.4.0    SunOS 4.0 for Sun-2, Sun-3, Sun-4
  32.     Makefile.sun.4.0+386i    SunOS 4.0 for Sun 386i
  33.     Makefile.sun.4.1    SunOS 4.1 for Sun-2, Sun-3, Sun-4
  34.     Makefile.sun4.3.2    SunOS Sys 4-3.2 for Sun-4
  35.     Makefile.ultrix.2.0    DEC Ultrix 2.0 - 2.2
  36.     Makefile.ultrix.3.0    DEC Ultrix 3.0
  37.  
  38.     (I also have a somewhat ancient implementation for V7 on a PDP-11 as well
  39.     as Unisoft Version 1.3 on a MC68000 if anyone is interested).
  40.  
  41.  
  42. #! /bin/sh
  43. # This is a shell archive.  Remove anything before this line, then feed it
  44. # into a shell via "sh file" or similar.  To overwrite existing files,
  45. # type "sh file -c".
  46. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  47. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  48. # Contents:  README getcmd.c printproc.c sps.l ttystatus.c waitingfor.c
  49. # Wrapped by rsalz@papaya.bbn.com on Mon Nov 26 14:03:21 1990
  50. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  51. echo If this archive is complete, you will see the following message:
  52. echo '          "shar: End of archive 1 (of 4)."'
  53. if test -f 'README' -a "${1}" != "-c" ; then 
  54.   echo shar: Will not clobber existing file \"'README'\"
  55. else
  56.   echo shar: Extracting \"'README'\" \(4769 characters\)
  57.   sed "s/^X//" >'README' <<'END_OF_FILE'
  58. X        SPS  -  Show Process Status
  59. X        ===========================
  60. X
  61. X
  62. XIntroduction:
  63. X    SPS is a intended to be used as a replacement for the standard
  64. X    ps(1) program. Its advantages over ps(1) are that it shows more
  65. X    useful information, that the displayed information is more
  66. X    comprehensible and that it is faster.
  67. X
  68. X
  69. X    SPS is currently implemented for the following operating systems and
  70. X    architectures.  The corresponding Makefiles are also shown here:
  71. X
  72. X    Makefile.4.1        Standard 4.1bsd for Vax
  73. X    Makefile.4.2        Standard 4.2bsd, Ultrix 1.x for Vax
  74. X    Makefile.4.3        Standard 4.3bsd (or 4.3-tahoe) for Vax
  75. X    Makefile.4.3+NFS    4.3bsd+NFS from Wisconsin (Mt. Xinu?, others?)
  76. X    Makefile.dec3100    DECStation 3100 + Ultrix 3.0 (incomplete)
  77. X    Makefile.sun.2.0    Sun 4.2 UNIX Release 2.0 - 2.2 for Sun-2
  78. X    Makefile.sun.3.0    Sun 4.2 UNIX Release 3.0 for Sun-2, Sun-3
  79. X    Makefile.sun.3.2    Sun 4.2 UNIX Release 3.2 for Sun-2, Sun-3
  80. X    Makefile.sun.4.0    SunOS 4.0 for Sun-2, Sun-3, Sun-4
  81. X    Makefile.sun.4.0+386i    SunOS 4.0 for Sun 386i
  82. X    Makefile.sun.4.1    SunOS 4.1 for Sun-2, Sun-3, Sun-4
  83. X    Makefile.sun4.3.2    SunOS Sys 4-3.2 for Sun-4
  84. X    Makefile.ultrix.2.0    DEC Ultrix 2.0 - 2.2
  85. X    Makefile.ultrix.3.0    DEC Ultrix 3.0
  86. X
  87. X    (I also have a somewhat ancient implementation for V7 on a PDP-11 as well
  88. X    as Unisoft Version 1.3 on a MC68000 if anyone is interested).
  89. X
  90. X
  91. XWhat SPS does:
  92. X    SPS displays wait channels symbolically, rather than as hexadecimal
  93. X    addresses.  (If you wish to teach SPS about a new sort of device,
  94. X    you must add an entry in the symbol table (globals2.c) as well as
  95. X    increasing the size of that table (NWAITSTATE in sps.h)).
  96. X
  97. X    SPS sorts processes before listing them, the order reflecting the
  98. X    relationship of the processes.  A child process is listed
  99. X    underneath its corresponding parent and is indented to depict the
  100. X    exact relationship.  SPS also indicates setuid processes.
  101. X
  102. X    SPS displays such values as the resident and virtual sizes of
  103. X    system processes.  It accepts a whole range of options to control
  104. X    the output.  By default, SPS lists information about one's own
  105. X    processes.  Other options instruct it to be verbose (the "v"
  106. X    option), to list all the command arguments of a process (the "w"
  107. X    option) or to list the environment strings of that process (the "e"
  108. X    option).  Similarly, there are options to control which processes
  109. X    are to be displayed.  The "a" option tells it to describe all
  110. X    processes and the "b" option tells it to describe "busy" processes;
  111. X    the latter is useful if you wish to find out what is loading your
  112. X    system.  There are also options to select the output according to
  113. X    user, controlling tty or process number.
  114. X
  115. X    SPS keeps its information in an information file; by default, this
  116. X    is /tmp/.spsinfo. This means that it can avoid having to do an
  117. X    expensive nlist() operation each time it is run.  It must be
  118. X    reinitialised (with the "i" option) if new users are added to
  119. X    /etc/passwd or if a new version of /vmunix is installed.
  120. X
  121. X
  122. XHow to build SPS:
  123. X    1. In order to compile and install SPS, first unbundle the four shell
  124. X       archive files.
  125. X    2. Check that the define statements in sps.h are large enough for
  126. X       your system.  In particular, you may need to increase MAXTTYS
  127. X       to reflect the number of tty devices in /dev.  The parameter
  128. X       MAXUSERS defines the maximum number of users defined in the
  129. X       password file (or through the Yellow Pages).  Because the
  130. X       user-ids are held in an internal hash table, this should
  131. X       probably be at least double the number of actual users.
  132. X    3. Choose an appropriate Makefile from the table above and compile
  133. X       the source files.  For example:
  134. X       % make -f Makefile.sun.3.2
  135. X    4. Try running SPS.  First, a suitable information file must be
  136. X       initialised.  It should then be able to display information
  137. X       concerning running processes on your system:
  138. X         # Initialise SPS.  Ignore any error messages at this stage.
  139. X       % sps i
  140. X         # Instruct SPS to list all active processes in verbose format.
  141. X       % sps va
  142. X    5. If this all works, install SPS with the appropriate Makefile
  143. X       and reinitialise it:
  144. X       % make -f Makefile.sun.3.2 install
  145. X       % sps -i
  146. X
  147. X
  148. XBug reports:
  149. X    Send all bug reports, fixes, comments and suggestions to Robert Ward at -
  150. X
  151. X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  152. X    J. Robert Ward,
  153. X    Olsen & Associates, Seefeldstrasse 233, CH-8008 Zuerich, Switzerland
  154. X
  155. XTel.:   +41 1 552224     Fax: +41 1 552282    Telex: 816656
  156. XEmail:  robert@olsen.uu.ch              Uucp:  uunet!chx400!olsen!robert
  157. XX.400:  s=robert/ou=olsen/o=uucp/p=switch/a=arcom/c=ch
  158. X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  159. END_OF_FILE
  160.   if test 4769 -ne `wc -c <'README'`; then
  161.     echo shar: \"'README'\" unpacked with wrong size!
  162.   fi
  163.   # end of 'README'
  164. fi
  165. if test -f 'getcmd.c' -a "${1}" != "-c" ; then 
  166.   echo shar: Will not clobber existing file \"'getcmd.c'\"
  167. else
  168.   echo shar: Extracting \"'getcmd.c'\" \(6872 characters\)
  169.   sed "s/^X//" >'getcmd.c' <<'END_OF_FILE'
  170. X# ifndef lint
  171. Xstatic char SccsId[] =  "@(#)getcmd.c    1.7\t8/6/90" ;
  172. X# endif
  173. X
  174. X# include       "sps.h"
  175. X# include       "flags.h"
  176. X# ifdef KVM
  177. X#  include      <kvm.h>
  178. X#  include      <ctype.h>
  179. X# else
  180. X#  include      <h/vm.h>
  181. X#  ifdef BSD42
  182. X#   include    <machine/pte.h>
  183. X#  else BSD42
  184. X#   include      <h/pte.h>
  185. X#  endif BSD42
  186. X# endif KVM
  187. X
  188. X/*
  189. X** GETCMD - Returns a character string read from a process' upage.
  190. X** This character string should represent the arguments to the current process.
  191. X*/
  192. Xchar    *getcmd ( p )
  193. X
  194. Xregister struct process         *p ;
  195. X
  196. X{
  197. X# ifdef KVM
  198. X    char                    **ap ;
  199. X    char                    *cp ;
  200. X    char                    *sp ;
  201. X    char                    **argv ;
  202. X    char                    **env ;
  203. X    extern kvm_t            *Flkvm ;
  204. X# else
  205. X    register int            *ip ;
  206. X    register char           *cp ;
  207. X    register char           *cp0 ;
  208. X    struct dblock           db ;
  209. X    struct pte              ptetbl[ UPAGES + CLSIZE ] ;
  210. X    extern int              Flmem, Flswap ;
  211. X# endif
  212. X    unsigned                nbad ;
  213. X    union
  214. X    {
  215. X        char            a_argc[ CLSIZE * NBPG ] ;
  216. X        int             a_argi[ CLSIZE * NBPG / sizeof( int ) ] ;
  217. X    } argbuf ;
  218. X    extern struct flags     Flg ;
  219. X    extern union userstate  User ;
  220. X    char                    *strcat(), *strncpy(), *strsave() ;
  221. X
  222. X    p->pr_csaved = 0 ;
  223. X    p->pr_upag = 0 ;
  224. X    if ( p->pr_p.p_stat == SZOMB )
  225. X        return ( "** Exit **" ) ;
  226. X    if ( !(p->pr_p.p_flag & SLOAD) && Flg.flg_o )
  227. X        return ( "** Swapped out **" ) ;
  228. X    /* Find the process' upage */
  229. X# ifdef KVM
  230. X    if ( !getupage( p ) )           
  231. X# else
  232. X    if ( !getupage( p, ptetbl ) )           
  233. X# endif
  234. X        return ( "** No upage **" ) ;
  235. X    p->pr_upag = 1 ;
  236. X    /* Is this a system process ? */
  237. X    if ( p->pr_p.p_flag & SSYS )            
  238. X        switch ( p->pr_p.p_pid )
  239. X        {
  240. X            case 0 :
  241. X                return ( "Unix Swapper" ) ;
  242. X            case 2 :
  243. X                return ( "Unix Pager" ) ;
  244. X# ifdef SUNOS40
  245. X            case 3 :
  246. X            case 4 :
  247. X                return ( "Unix Idle" ) ;
  248. X# endif
  249. X            default :
  250. X                break ;
  251. X        }
  252. X# ifdef DEC3100
  253. X    /* Reading the command arguments doesn't work on the DEC 3100 so
  254. X       we resort to this kludge until one day it does. */
  255. X    if ( 1 )
  256. X# else DEC3100
  257. X    if ( Flg.flg_c )
  258. X# endif DEC3100
  259. X    {
  260. X        p->pr_csaved = 1 ;
  261. X        (void)strncpy( argbuf.a_argc, User.u_us.u_comm,
  262. X            sizeof( User.u_us.u_comm ) ) ;
  263. X        argbuf.a_argc[ sizeof ( User.u_us.u_comm ) ] = '\0' ;
  264. X        return ( strsave( argbuf.a_argc ) ) ;
  265. X    }
  266. X# ifdef KVM
  267. X    if ( kvm_getcmd( Flkvm, &p->pr_p, &User.u_us, &argv,
  268. X        Flg.flg_e ? &env : (char ***)NULL ) < 0 || argv == NULL )
  269. X            goto getsysargs ;
  270. X    p->pr_csaved = 1 ;
  271. X    sp = argbuf.a_argc ;
  272. X    nbad = 0 ;
  273. X    ap = argv ;
  274. X    do {
  275. X        /* Copy one string from argv or env */
  276. X        for ( cp = *ap++; *cp; )
  277. X            if ( isprint( *cp ) )
  278. X                *sp++ = *cp++ ;
  279. X            else
  280. X            {
  281. X                /* Replace control characters with ?'s */
  282. X                if ( ++nbad > 5 )
  283. X                {
  284. X                      *sp++ = ' ' ;
  285. X                      break ;
  286. X                  }
  287. X                *sp++ = '?' ;
  288. X                cp++ ;
  289. X            }
  290. X        *sp++ = ' ' ;
  291. X        /* Check if at end of argv and user wants to see env */
  292. X        if ( *ap == 0 && Flg.flg_e && argv != 0 )
  293. X        {
  294. X            free( (char *) argv ) ;
  295. X            argv = NULL ;
  296. X            ap = env ;
  297. X            if ( ap == NULL )
  298. X                break ;
  299. X        }
  300. X    } while ( *ap ) ;
  301. X     if ( Flg.flg_e )
  302. X                free( (char*)env ) ;
  303. X    while ( *--sp == ' ' )
  304. X        *sp = '\0' ;
  305. X    return ( strsave( argbuf.a_argc ) ) ;
  306. X# else
  307. X    /* Fix by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
  308. X    /* Check for lack of stack, jack! (Sun 3.0 biod's) */
  309. X    if (User.u_us.u_ssize == 0)
  310. X        goto getsysargs ;
  311. X    /* Look at the top of the upage to locate the command arguments.
  312. X       The page is loaded if the process itself is loaded and the pte
  313. X       contains is marked as valid. */
  314. X    if ( (p->pr_p.p_flag & SLOAD)
  315. X    && !ptetbl[0].pg_fod && ptetbl[0].pg_pfnum )
  316. X    {       /* If the page is loaded, read the arguments from
  317. X           physical memory. */
  318. X        memseek( Flmem, (long)ctob( ptetbl[0].pg_pfnum ) ) ;
  319. X        if ( read( Flmem, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
  320. X            return ( "** Memory read error **" ) ;
  321. X    }
  322. X    else                            
  323. X    {       /* Otherwise the page is on the swap device */
  324. X        vstodb( 0, ctod( CLSIZE ), &User.u_us.u_smap, &db, 1 ) ;
  325. X#  ifdef BSD42
  326. X        swseek( (long)dtob( db.db_base ) ) ;
  327. X#  else
  328. X        swseek( (long)ctob( db.db_base ) ) ;
  329. X#  endif
  330. X        if ( Flg.flg_o )
  331. X            return ( "** Swapped page **" ) ;
  332. X        if ( read( Flswap, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
  333. X            return ( "** Swap device read error **" ) ;
  334. X    }
  335. X    /* Look down until the end of command arguments is found. */
  336. X    ip = &argbuf.a_argi[ CLSIZE*NBPG / sizeof( int ) ] ;
  337. X    ip -= 2 ;
  338. X    while ( *--ip )
  339. X        if ( ip == &argbuf.a_argi[0] )
  340. X            goto getsysargs ;
  341. X    p->pr_csaved = 1 ;
  342. X    /* Process the command arguments, looking for nulls and unprintable
  343. X       characters. */
  344. X    cp0 = (char*)(ip + 1) ;
  345. X    if ( !*cp0 )                    
  346. X        cp0++ ;                 
  347. X    if ( *cp0 )
  348. X    {
  349. X        nbad = 0 ;                      
  350. X        for ( cp = cp0 ; cp < &argbuf.a_argc[ CLSIZE*NBPG ] ; cp++ )
  351. X        {
  352. X            *cp &= 0177 ;
  353. X            if ( !*cp )             
  354. X            {       /* Replace nulls with spaces */
  355. X                *cp = ' ' ;
  356. X                continue ;
  357. X            }
  358. X            if ( *cp < ' ' || *cp == 0177 )
  359. X            {       /* Replace control characters with ?'s */
  360. X                if ( ++nbad > 5 )
  361. X                {
  362. X                    *cp++ = ' ' ;
  363. X                    break ;
  364. X                }
  365. X                *cp = '?' ;
  366. X                continue ;
  367. X            }
  368. X            if ( !Flg.flg_e && *cp == '=' )
  369. X            {       /* Break on an `=' if we are not interested
  370. X                   in the environment strings. */
  371. X                *cp = '\0' ;
  372. X                while ( cp > cp0 && *--cp != ' ' )
  373. X                    *cp = '\0' ;
  374. X                break ;
  375. X            }
  376. X        }
  377. X        while ( *--cp == ' ' )
  378. X            *cp = '\0' ;
  379. X        return ( strsave( cp0 ) ) ;
  380. X    }
  381. X# endif KVM
  382. Xgetsysargs :
  383. X    /* If the command arguments cannot be accessed from the user's memory
  384. X       space, get the command name from the system's idea of what the
  385. X       name should be. */
  386. X    p->pr_csaved = 1 ;
  387. X    argbuf.a_argc[0] = '(' ;
  388. X    (void)strncpy( &argbuf.a_argc[1], User.u_us.u_comm,
  389. X        sizeof( User.u_us.u_comm ) ) ;
  390. X    argbuf.a_argc[ sizeof ( User.u_us.u_comm ) + 1 ] = '\0' ;
  391. X    (void)strcat( &argbuf.a_argc[0], ")" ) ;
  392. X    return ( strsave( argbuf.a_argc ) ) ;
  393. X}
  394. X
  395. X# ifndef KVM
  396. X/*
  397. X** VSTODB - Given a base/size pair in virtual swap area,
  398. X** return a physical base/size pair which is the
  399. X** (largest) initial, physically contiguous block.
  400. X/* This code is stolen from the kernel file /sys/sys/vm_drum.c.
  401. X*/
  402. Xvstodb ( vsbase, vssize, dmp, dbp, rev )
  403. X
  404. Xregister int                    vsbase ;
  405. Xregister int                    vssize;
  406. Xstruct dmap                     *dmp ;
  407. Xregister struct dblock          *dbp ;
  408. Xint                             rev ;
  409. X
  410. X{
  411. X    register int            blk ;
  412. X    register swblk_t        *ip ;
  413. X# ifdef BSD42
  414. X    extern struct info      Info ;
  415. X# endif
  416. X
  417. X# ifdef BSD42
  418. X    blk = Info.i_dmmin ;
  419. X# else
  420. X    blk = DMMIN ;
  421. X# endif
  422. X    ip = dmp->dm_map ;
  423. X    while ( vsbase >= blk )
  424. X    {
  425. X        vsbase -= blk ;
  426. X# ifdef BSD42
  427. X        if ( blk < Info.i_dmmax )
  428. X# else
  429. X        if ( blk < DMMAX )
  430. X# endif
  431. X            blk *= 2 ;
  432. X        ip++ ;
  433. X    }
  434. X    dbp->db_size = vssize < blk - vsbase ? vssize : blk - vsbase ;
  435. X    dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
  436. X}
  437. X# endif
  438. END_OF_FILE
  439.   if test 6872 -ne `wc -c <'getcmd.c'`; then
  440.     echo shar: \"'getcmd.c'\" unpacked with wrong size!
  441.   fi
  442.   # end of 'getcmd.c'
  443. fi
  444. if test -f 'printproc.c' -a "${1}" != "-c" ; then 
  445.   echo shar: Will not clobber existing file \"'printproc.c'\"
  446. else
  447.   echo shar: Extracting \"'printproc.c'\" \(6875 characters\)
  448.   sed "s/^X//" >'printproc.c' <<'END_OF_FILE'
  449. X# ifndef lint
  450. Xstatic char SccsId[] =  "@(#)printproc.c    1.2\t8/2/90" ;
  451. X# endif
  452. X
  453. X# include       "sps.h"
  454. X# include       "flags.h"
  455. X# ifndef SUNOS40
  456. X# include       <h/text.h>
  457. X# endif
  458. X
  459. X# ifdef SUNOS40
  460. X#  ifdef OLDSTATS
  461. X#   define OFFSET 8
  462. X#  else
  463. X#   define OFFSET 3
  464. X#  endif
  465. X# else
  466. X#   define OFFSET 0
  467. X# endif
  468. X
  469. X/* PRINTPROC - Pretty print a process according to the switches. */
  470. Xprintproc ( p, md )
  471. X
  472. Xregister struct process         *p ;            
  473. Xint                             md ;            
  474. X
  475. X{
  476. X    register char           *chp ;
  477. X# ifndef SUNOS40
  478. X    register struct text    *tp ;
  479. X# endif
  480. X    register struct hashtab *hp ;
  481. X    char                    chbuf[10] ;
  482. X    time_t                  time ;
  483. X    time_t                  chtime ;
  484. X# ifdef BSD42
  485. X    time_t                  utime ;
  486. X    time_t                  uchtime ;
  487. X# endif
  488. X    extern short            Lastuid, Lastpgrp ;
  489. X    extern struct flags     Flg ;
  490. X    char                    *waitingfor() ;
  491. X    struct hashtab          *hashuid() ;
  492. X    double                  percentmem() ;
  493. X
  494. X    /* List tty name and foreground/background/detached information */
  495. X    printf( "%2.2s%c", p->pr_tty->l_name,
  496. X# ifdef SDETACH
  497. X        !p->pr_p.p_pgrp ? ' ' : p->pr_p.p_flag & SDETACH ? '_' :
  498. X        p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ;
  499. X# else
  500. X        !p->pr_p.p_pgrp || p->pr_p.p_pgrp != p->pr_tty->l_pgrp ?
  501. X# ifdef SPGLDR
  502. X        p->pr_p.p_flag & SPGLDR ? '-' :
  503. X# endif
  504. X           ' ' :
  505. X# ifdef SPGLDR
  506. X        p->pr_p.p_flag & SPGLDR ? '+' :
  507. X# endif
  508. X           '.' ) ;
  509. X# endif
  510. X    hp = hashuid( (int)p->pr_p.p_uid ) ;
  511. X    if ( !md  )                             
  512. X    {       /* If a top-level process, list the user name */
  513. X        if ( hp )
  514. X            printf( "%-8.8s ", hp->h_uname ) ;
  515. X        else
  516. X            printf( "user%-4.4d ", p->pr_p.p_uid ) ;
  517. X    }
  518. X    else                                    
  519. X    {       /* Usually list an asterisk for a child process */
  520. X        md = md > 8 ? 8 : md ;
  521. X        printf( "%*s%c", md, "",
  522. X            p->pr_p.p_pgrp == Lastpgrp ? '|' : '*' ) ;      
  523. X        /* But beware of setuid processes */
  524. X        md = 8 - md ;
  525. X        if ( p->pr_p.p_uid == Lastuid )
  526. X            printf( "%-*.*s", md, md, "" ) ;
  527. X        else if ( hp )
  528. X            printf( "%-*.*s", md, md, hp->h_uname ) ;
  529. X        else
  530. X        {
  531. X            md -= 4 ;
  532. X            printf( "user%-*.*d", md, md, p->pr_p.p_uid ) ;
  533. X        }
  534. X    }
  535. X    Lastuid = p->pr_p.p_uid ;
  536. X    Lastpgrp = p->pr_p.p_pgrp ;
  537. X    if ( Flg.flg_d )                        
  538. X    {       /* List disc I/O and paging information */
  539. X        if ( !p->pr_upag || p->pr_p.p_stat == SZOMB )
  540. X        {
  541. X            prcmd( p, 49, -63 ) ;
  542. X            return ;
  543. X        }
  544. X        printf( "%2d %8d+%8d %4d %8d %8D ",
  545. X            p->pr_files,
  546. X# ifdef BSD42
  547. X            p->pr_rself.ru_majflt,
  548. X            p->pr_rself.ru_minflt,
  549. X            p->pr_rself.ru_nswap,
  550. X            p->pr_rself.ru_inblock + p->pr_rself.ru_oublock,
  551. X            KBYTES( p->pr_rself.ru_idrss + p->pr_rself.ru_isrss
  552. X                + p->pr_rself.ru_ixrss ) ) ;
  553. X# else
  554. X            p->pr_vself.vm_majflt,
  555. X            p->pr_vself.vm_minflt,
  556. X            p->pr_vself.vm_nswap,
  557. X            p->pr_vself.vm_inblk + p->pr_vself.vm_oublk,
  558. X            KBYTES( (p->pr_vself.vm_idsrss
  559. X                + p->pr_vself.vm_ixrss) / Info.i_hz ) ) ;
  560. X# endif
  561. X        prcmd( p, 5, -63 ) ;
  562. X        return ;
  563. X    }
  564. X    if ( !Flg.flg_v )                       
  565. X    {       /* Not verbose so just list command arguments */
  566. X        prcmd( p, 5, -19 ) ;
  567. X        return ;
  568. X    }
  569. X    /* Arrive here if being verbose ; list cpu information */
  570. X    switch ( p->pr_p.p_stat )               
  571. X    {                                       
  572. X        case SSLEEP :
  573. X        case SWAIT :
  574. X        case SIDL :
  575. X            /* Determine why a process should be in a wait state */
  576. X            chp = waitingfor( p ) ;
  577. X            break ;
  578. X        case SRUN :
  579. X            chp = "run" ;
  580. X            break ;
  581. X        case SZOMB :
  582. X            chp = "exit" ;
  583. X            break ;
  584. X        case SSTOP :
  585. X            chp = "stop" ;
  586. X            break ;
  587. X    }
  588. X    /* If the process is loaded, list the status information in capitals */
  589. X    printf( "%-6.6s ", p->pr_p.p_flag & SLOAD ?
  590. X        (capitals( chp, chbuf ), chbuf) : chp ) ;
  591. X    /* List process flags */
  592. X    printf( "%c%c%c", p->pr_p.p_flag & SSYS ? 'U' :
  593. X        p->pr_p.p_flag & STRC ? 'T' : ' ',
  594. X        p->pr_p.p_flag & SVFORK ? 'V' :
  595. X        p->pr_p.p_flag & SPHYSIO ? 'I' : ' ',
  596. X        p->pr_p.p_flag & SUANOM ? 'A' :
  597. X        p->pr_p.p_flag & SSEQL ? 'S' : ' ' ) ;
  598. X    /* List process niceness */
  599. X    if ( p->pr_p.p_nice != NZERO )          
  600. X        printf( "%3d ", p->pr_p.p_nice - NZERO ) ;
  601. X    else
  602. X        printf( "    " ) ;
  603. X    if ( p->pr_p.p_stat == SZOMB )
  604. X    {
  605. X        prcmd( p, 41 - OFFSET, OFFSET - 69 ) ;
  606. X        return ;
  607. X    }                                       
  608. X# ifdef SUNOS40
  609. X#  ifdef OLDSTATS
  610. X    /* List process virtual and real sizes */
  611. X    printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
  612. X#  else
  613. X    /* List process private and shared virtual and real sizes */
  614. X        printf("%4d", KBYTES( p->pr_private ) ) ;
  615. X        printf("+%4d", KBYTES( p->pr_shared ) ) ;
  616. X#  endif
  617. X    printf( " %4d", KBYTES( p->pr_p.p_rssize ) ) ;
  618. X# else
  619. X    /* List process and text virtual sizes */
  620. X    printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
  621. X    if ( tp = p->pr_p.p_textp )
  622. X        printf( "+%3d ", KBYTES( tp->x_size ) ) ;
  623. X    else
  624. X        printf( "     " ) ;
  625. X    /* List process and text real sizes */
  626. X    printf( "%4d", KBYTES( p->pr_p.p_rssize ) ) ;
  627. X    if ( tp )
  628. X        printf( "+%3d", KBYTES( tp->x_rssize ) ) ;
  629. X    else
  630. X        printf( "    " ) ;
  631. X# endif
  632. X    printf( " %2.0f ", percentmem( p ) ) ;
  633. X    /* List information obtained from the upage. This includes the process
  634. X       times and command arguments. */
  635. X    if ( !p->pr_upag )
  636. X    {
  637. X        prcmd( p, 20, OFFSET - 69 ) ;
  638. X        return ;
  639. X    }                                       
  640. X    /* List process time information */
  641. X# ifdef BSD42
  642. X    time   = Flg.flg_q ? p->pr_rself.ru_utime.tv_sec :
  643. X         p->pr_rself.ru_utime.tv_sec + p->pr_rself.ru_stime.tv_sec ;
  644. X    utime  = Flg.flg_q ? p->pr_rself.ru_utime.tv_usec :
  645. X         p->pr_rself.ru_utime.tv_usec + p->pr_rself.ru_stime.tv_usec ;
  646. X    chtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_sec :
  647. X         p->pr_rchild.ru_utime.tv_sec + p->pr_rchild.ru_stime.tv_sec ;
  648. X    uchtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_usec :
  649. X         p->pr_rchild.ru_utime.tv_usec + p->pr_rchild.ru_stime.tv_usec ;
  650. X    prcpu( time, utime ) ;
  651. X    if ( chtime != 0L )
  652. X    {
  653. X        printf( "+" ) ;
  654. X        prcpu( chtime, uchtime ) ;
  655. X    }
  656. X# else
  657. X    time   = Flg.flg_q ? p->pr_vself.vm_utime :
  658. X         p->pr_vself.vm_utime + p->pr_vself.vm_stime ;
  659. X    chtime = Flg.flg_q ? p->pr_vchild.vm_utime :
  660. X         p->pr_vchild.vm_utime + p->pr_vchild.vm_stime ;
  661. X    prcpu( time ) ;
  662. X    if ( chtime != 0L )
  663. X    {
  664. X        printf( "+" ) ;
  665. X        prcpu( chtime ) ;
  666. X    }
  667. X# endif
  668. X    else
  669. X        printf( "      " ) ;
  670. X# ifdef BSD42
  671. X    if ( time || utime )
  672. X# else
  673. X    if ( time )
  674. X# endif
  675. X# ifdef SUN
  676. X        printf( " %2.0f ", (double)p->pr_p.p_pctcpu * 100.0/FSCALE ) ;
  677. X# else
  678. X#  ifdef DEC3100
  679. X        printf( " %2.0f ", p->pr_p.p_pctcpu ) ;
  680. X#  else
  681. X        printf( " %2.0f ", p->pr_p.p_pctcpu * 100.0 ) ;
  682. X#  endif DEC3100
  683. X# endif SUN
  684. X    else
  685. X        printf( "    " ) ;
  686. X    /* Finally, list the process command arguments. */
  687. X    prcmd( p, 5, OFFSET - 69 ) ;                    
  688. X}
  689. X
  690. X/* CAPITALS - Converts letters in `chp' to upper-case in buffer `buf'. */
  691. Xcapitals ( chp, buf )
  692. X
  693. Xregister char                   *chp ;
  694. Xregister char                   *buf ;
  695. X
  696. X{
  697. X    while ( *buf = *chp++ )
  698. X    {
  699. X        if ( 'a' <= *buf && *buf <= 'z' )
  700. X            *buf -= 'a' - 'A' ;
  701. X        buf++ ;
  702. X    }
  703. X}
  704. END_OF_FILE
  705.   if test 6875 -ne `wc -c <'printproc.c'`; then
  706.     echo shar: \"'printproc.c'\" unpacked with wrong size!
  707.   fi
  708.   # end of 'printproc.c'
  709. fi
  710. if test -f 'sps.l' -a "${1}" != "-c" ; then 
  711.   echo shar: Will not clobber existing file \"'sps.l'\"
  712. else
  713.   echo shar: Extracting \"'sps.l'\" \(15259 characters\)
  714.   sed "s/^X//" >'sps.l' <<'END_OF_FILE'
  715. X.if n .pl 66
  716. X.TH SPS 1
  717. X.SH NAME
  718. Xsps \ \ \-\ \ \ show process status
  719. X.SH SYNOPSIS
  720. X\fBsps\ \fP \ [ \fB\-cdefgijkoqrslvwyABDFNPSTUWZ\fP ]\ \ [
  721. X\fIprocess\ .\ .\ .\ | tty\ .\ .\ .\ | user\ .\ .\ .\fP ]
  722. X.SH DESCRIPTION
  723. X\fISps\fP reports information concerning system processes.
  724. XIt shows the current state of any process by
  725. Xlisting information such as ownership, CPU time usage, memory usage
  726. Xand disc activity.
  727. X.PP
  728. X\fISps\fP should be used in preference to \fIps\fP(1)
  729. Xbecause it is faster and the output is more comprehensive and more
  730. Xcomprehensible.
  731. X.SH OPTIONS
  732. XBy default, \fIsps\fP prints basic information about one's own processes.
  733. XThe various options described below select other processes or make
  734. X\fIsps\fP more verbose.
  735. X.PP
  736. XUpper case options select processes to be described.
  737. XLower case options specify the format of the output.
  738. XFor instance, the options \fBBv\fP specify that \fIsps\fP
  739. Xshould list ``busy'' processes in a verbose format.
  740. XUnless there is any conflict, lower case options may be used
  741. Xinstead of upper case options, and vice versa.
  742. X.PP
  743. XThe following options specify the format of the listed output \-
  744. X.TP 8
  745. X\fB\-c\fP
  746. XUse the system's idea of the command, rather than getting the arguments
  747. Xfrom user space.  While somewhat less informative, this is faster and
  748. Xmore reliable.
  749. X.TP
  750. X\fB\-d\fP
  751. XList output reflecting how each process affects the
  752. Xdisc and paging activity of the system.
  753. X.TP
  754. X\fB\-e\fP
  755. XList the environment passed to each process.
  756. X.TP
  757. X\fB\-f\fP
  758. XInclude the process\-id of the parent of each process.
  759. X.TP
  760. X\fB\-g\fP
  761. XInclude the process group of each process.
  762. X.TP
  763. X\fB\-o\fP
  764. XAvoid looking at the swap device (\fB/dev/drum\fP). This tends to make \fIsps\fP
  765. Xrun faster, although no information concerning swapped processes
  766. Xcan be obtained.
  767. X.TP
  768. X\fB\-q\fP
  769. XBy default, \fIsps\fP
  770. Xlists the sum of the user plus system times under the
  771. X\fITime\fP and \fIChild\fP fields.  This option forces \fIsps\fP
  772. Xto list only the user times.
  773. X.TP
  774. X\fB\-r\fP
  775. XRepeat the output indefinitely.
  776. XIf the next argument is numeric, \fIsps\fP repeats the output with that
  777. Xmany seconds delay between each repetition.
  778. XOtherwise the output is repeated with no delay.
  779. X.TP
  780. X\fB\-l\fP
  781. X.br
  782. X.ns
  783. X.TP
  784. X\fB\-v\fP
  785. XList additional information in a verbose format. See below.
  786. X.TP
  787. X\fB\-w\fP
  788. XList output in a wide format.  This option forces \fIsps\fP
  789. Xto print all the command arguments, even if doing so extends the output
  790. Xbeyond one line.
  791. X.TP
  792. X\fB\-y\fP
  793. XShow the status of each terminal line.
  794. X.PP
  795. XThe following options specify which processes are to be described \-
  796. X.TP 8
  797. X\fB\-A\fP
  798. XList all processes.
  799. X.TP
  800. X\fB\-B\fP
  801. XList busy processes.  A process is considered to be busy
  802. Xif it is immediately runnable or awaiting a fast event such as disc I/O.
  803. X.TP
  804. X\fB\-D\fP
  805. XList detached processes.
  806. X.TP
  807. X\fB\-F\fP
  808. XList foreground processes.
  809. X.TP
  810. X\fB\-N\fP
  811. XShow no processes at all. Only the summary line is printed.
  812. X.TP
  813. X\fB\-P\fP
  814. XList only processes whose identifiers are specified in the following arguments.
  815. X.TP
  816. X\fB\-S\fP
  817. XList stopped processes.
  818. X.TP
  819. X\fB\-T\fP
  820. XList only processes attached to the following specified terminals.
  821. X.TP
  822. X\fB\-U\fP
  823. XList only processes belonging to the following specified users.
  824. X.TP
  825. X\fB\-W\fP
  826. XList waiting processes.
  827. X.TP
  828. X\fB\-Z\fP
  829. XList zomby (exiting) processes.
  830. X.PP
  831. XThe following are miscellaneous options \-
  832. X.TP 8
  833. X\fB\-i\fP
  834. XInitialise \fIsps\fP.
  835. XThis is necessary if new users are added to the password file,
  836. Xor if a new version of UNIX is installed.
  837. XSps builds a new information file summarising pertinent information
  838. Xread from the password file (\fB/etc/passwd\fP), the executable kernel image
  839. X(\fB/vmunix\fP) and the directory of tty devices (\fB/dev\fP).
  840. XSee also the \fB\-j\fP and \fB\-s\fP options.
  841. X.TP
  842. X\fB\-j\fP
  843. XSpecify an information file other than the default (\fB/etc/spsinfo\fP).
  844. XThe next argument is taken to be the name of a suitable information file.
  845. XIf the \fB\-i\fP flag is also specified, \fIsps\fP builds a
  846. Xnew information file with the given name.
  847. XOtherwise, \fBsps\fP reads previously created summarising information
  848. Xfrom that file.
  849. X.TP
  850. X\fB\-k\fP
  851. XUse a specific disc file rather than the default physical
  852. Xmemory (\fB/dev/mem\fP)
  853. Xand kernel virtual memory (\fB/dev/kmem\fP) files. The next argument is taken
  854. Xto be the name of a suitable memory dump file.
  855. XThis flag automatically sets the \fB\-o\fP flag.
  856. X.TP
  857. X\fB\-s\fP
  858. XThis option is used in conjunction with the \fB\-i\fP option.
  859. XThe next argument is taken to be the name of a suitable kernel executable
  860. Xfile, rather than the default (\fB/vmunix\fP).
  861. X\fISps\fP looks at the symbol table of this file to determine
  862. Xthe virtual addresses of various kernel structures.
  863. X.SH OUTPUT
  864. X\fISps\fP produces output in the following fields \-
  865. X.TP 8
  866. X\fITy\fP
  867. XThe terminal identifier to which the process is attached.
  868. X.IP
  869. XIf this is followed by an underscore, the process is detached.
  870. XIf it is followed by a period, the process is running in the foreground.
  871. XOtherwise the process is running in the background but is still
  872. Xattached to a terminal.
  873. X.TP
  874. X\fIUser\fP
  875. XThe symbolic name of the process' effective user-id (see \fIexec\fP(2)
  876. Xand \fIsetuid\fP(2)).
  877. XThis name is defined by the system password file (\fB/etc/passwd\fP)
  878. Xwhen \fIsps\fP was last initialised.
  879. XOtherwise, an asterisk (\fB*\fP) or vertical bar (\fB|\fP) appearing in this
  880. Xcolumn denotes that the process is an immediate relative of the
  881. Xpreceding process.
  882. XA bar is listed, rather than an asterisk, if both processes belong
  883. Xto the same process group.
  884. XA user name is listed only if the effective user-id
  885. Xdiffers from that of the preceding process or if it is a top-level
  886. Xprocess (immediate offspring of process 1).
  887. X.TP
  888. X\fIProc#\fP
  889. XThe unique process identifier.
  890. X.TP
  891. X\fIPpid#\fP
  892. XThe process-id of the process' parent.
  893. X.TP
  894. X\fIPgrp#\fP
  895. XThe process group to which the process belongs.
  896. X.TP
  897. X\fICommand\fP
  898. XThe command arguments obtained from the process' own address space.
  899. X(If the command name appears in parentheses, \fIsps\fP
  900. Xwas unable to locate the arguments in user space and so reports
  901. Xthe system's idea of the command name.)
  902. X.PP
  903. XThe following additional fields are listed when \fIsps\fP
  904. Xis invoked with one of the \fB\-l\fP or \fB\-v\fP options \-
  905. X.TP 8
  906. X\fIStatus\fP
  907. XThe process' current state.
  908. XIf this field is listed in upper-case letters, the process is currently
  909. Xloaded in real memory space ; otherwise it has been swapped out.
  910. XThe status field may contain one of the following descriptions \-
  911. X.RS 8
  912. X.TP 16
  913. X\fIrun\fP
  914. XThe process can be run immediately.
  915. X.TP
  916. X\fIstop\fP
  917. XThe process is stopped. See \fIsigvec\fP(2).
  918. X.TP
  919. X\fIexit\fP
  920. XThe process is a zomby.
  921. X.RE
  922. X.IP
  923. XAny other entry in the status field indicates the process is
  924. Xwaiting for some external event to occur.
  925. XThis is usually for one of the reasons listed below.
  926. X(If \fIsps\fP does not know why a process is waiting, it lists
  927. Xthe hexadecimal address of the process' wait channel,
  928. Xwith the initial 80000000 trimmed off.)
  929. XA process may be waiting for one of the following reasons \-
  930. X.RS 8
  931. X.TP 16
  932. X\fIchild\fP
  933. XThe process is waiting for a child to terminate. See \fIwait\fP(2).
  934. X.TP
  935. X\fIpause\fP
  936. XWaiting for a signal to be received. See \fIsigpause\fP(2).
  937. X.TP
  938. X\fIswap\fP
  939. XWaiting for a page to be swapped in.
  940. X.TP
  941. X\fIrswbuf\fP
  942. XWaiting for a read from the swap device \fB/dev/drum.\fP
  943. X.TP
  944. X\fIdiscio\fP
  945. XWaiting for a disc read or write operation.
  946. X(Actually, this means that the process is waiting for an operation
  947. Xthrough the kernel's I/O buffering mechanism to complete, but \fIdiscio\fP
  948. Xis what is generally meant here).
  949. X.TP
  950. X\fIrpipe\fP
  951. X.br
  952. X.ns
  953. X.TP
  954. X\fIwpipe\fP
  955. XWaiting for a read from an empty pipe.  Alternatively, the process
  956. Xis waiting to write to a full pipe. See \fIpipe\fP(2).
  957. X.TP
  958. X\fIrsockt\fP
  959. X.br
  960. X.ns
  961. X.TP
  962. X\fIwsockt\fP
  963. XWaiting for a read from an empty socket.
  964. XAlternatively, the process is waiting to write to a full socket (4.[2\-]bsd only).
  965. X.TP
  966. X\fIaccept\fP
  967. XWaiting to accept a stream-based socket connection (4.[2\-]bsd only).
  968. XSee \fIaccept\fP(2).
  969. X.TP
  970. X\fIconnct\fP
  971. XWaiting to establish a connection through a stream-based socket to a
  972. Xremote process (4.[2\-]bsd only). See \fIconnect\fP(2).
  973. X.TP
  974. X\fIsocket\fP
  975. XWaiting for some other time-out event on a socket (4.[2\-]bsd only).
  976. X.TP
  977. X\fIselect\fP
  978. XBlocked by a \fIselect\fP(2) system call (4.[2\-]bsd only).
  979. X.TP
  980. X\fIrmux\fP
  981. XWaiting for a read from a multiplexor file (4.1bsd only).
  982. X.TP
  983. X\fIinode\fP
  984. XWaiting for an inode to be allocated or unlocked.
  985. X.TP
  986. X\fIexlock\fP
  987. X.br
  988. X.ns
  989. X.TP
  990. X\fIshlock\fP
  991. XWaiting for a file to become unlocked. See \fIflock\fP(2).
  992. X.TP
  993. X\fIrtty??\fP
  994. X.br
  995. X.ns
  996. X.TP
  997. X\fIwtty??\fP
  998. X.br
  999. X.ns
  1000. X.TP
  1001. X\fIotty??\fP
  1002. XWaiting for a read or write to the specified terminal, or for the terminal
  1003. Xto be switched on. See \fItty\fP(4).
  1004. XAlternatively, waiting for a read or write to the
  1005. Xspecified slave pty device. See \fIpty\fP(4).
  1006. X.TP
  1007. X\fIitty??\fP
  1008. X.br
  1009. X.ns
  1010. XUnder SunOS, waiting perform I/O to an iconified window.
  1011. X.TP
  1012. X\fIrpty??\fP
  1013. X.br
  1014. X.ns
  1015. X.TP
  1016. X\fIwpty??\fP
  1017. XWaiting for a read or write to the specified master pty device.
  1018. XSee \fIpty\fP(4).
  1019. X.TP
  1020. X\fIptrace\fP
  1021. XThis is a parent process tracing its child.
  1022. X.TP
  1023. X\fIvfork\fP
  1024. XThis is a vforking parent process waiting for its child to relinquish
  1025. Xmemory resources. See \fIvfork\fP(2).
  1026. X.TP
  1027. X\fIfloppy\fP
  1028. X.br
  1029. X.ns
  1030. X.TP
  1031. X\fIprintr\fP
  1032. X.br
  1033. X.ns
  1034. X.TP
  1035. X\fIr??buf\fP
  1036. XWaiting for the specified device to complete an I/O operation.
  1037. X.RE
  1038. X.TP 8
  1039. X\fIFl\fP
  1040. XFlags associated with the current state of the process.
  1041. XThese flags may be any of the following \-
  1042. X.RS 8
  1043. X.TP 16
  1044. X\fIU\fP
  1045. XThe process is a UNIX system process.
  1046. X.TP
  1047. X\fIT\fP
  1048. XThe process is being traced or debugged.
  1049. X.TP
  1050. X\fIV\fP
  1051. XThe process is a child currently being vforked. See \fIvfork\fP(2).
  1052. X.TP
  1053. X\fII\fP
  1054. XThe process is undergoing physical I/O.
  1055. X.TP
  1056. X\fIA\fP
  1057. XThe system has detected, or the user has warned of
  1058. Xanomalous paging behaviour. See \fIvadvise\fP(2).
  1059. X.RE
  1060. X.TP 8
  1061. X\fINice\fP
  1062. XThe ``niceness'' of the process. See \fInice\fP(2).
  1063. X.TP
  1064. X\fIVirtual\fP
  1065. XThe virtual memory size of the process in kilobytes.
  1066. XThe first figure indicates the sum of the data and stack segments,
  1067. Xthe second figure that of the text segment.
  1068. X.TP
  1069. X\fIResident\fP
  1070. XThe resident memory size of the process in kilobytes, representing
  1071. Xthe real memory devoted to the process.
  1072. X.TP
  1073. X\fI%M\fP
  1074. XThe percentage of available real memory allocated to this process.
  1075. X.TP
  1076. X\fITime\fP
  1077. XThe total CPU time accumulated by this process.
  1078. X(This is the sum of the system plus user times, unless the \fB\-q\fP
  1079. Xflag is specified in which case only the user time is listed.)
  1080. X.TP
  1081. X\fIChild\fP
  1082. XThe total CPU time accumulated by the process' children.
  1083. X(This is the sum of the system plus user times, unless the \fB\-q\fP
  1084. Xflag is specified.)
  1085. X.TP
  1086. X\fI%C\fP
  1087. XThe percentage of available CPU time devoted to the process.
  1088. XThis figure is a decaying average, computed over the past second.
  1089. X.PP
  1090. XThe following fields are listed when \fIsps\fP is invoked with the
  1091. X\fB\-d\fP option \-
  1092. X.TP 8
  1093. X\fIFiles\fP
  1094. XThe number of open files for this process.
  1095. X.TP
  1096. X\fIPageFaults\fP
  1097. XThe number of major and minor page faults incurred by the process.
  1098. X.TP
  1099. X\fISwap\fP
  1100. XThe number of swaps incurred by the process.
  1101. X.TP
  1102. X\fIBlockI/O\fP
  1103. XThe number of block read or write operations performed
  1104. Xon behalf of the process.
  1105. X.TP
  1106. X\fIKbytesecs\fP
  1107. XThe integral of real memory usage over time.
  1108. XThus, if a process uses 60 kilobytes of real memory for 3 seconds,
  1109. Xthis figure is incremented by 180.
  1110. X.PP
  1111. XThe following fields are listed when \fIsps\fP is invoked with the
  1112. X\fB\-y\fP option \-
  1113. X.TP 8
  1114. X\fIDev\fP
  1115. XThe major and minor device numbers of the terminal.
  1116. X.TP
  1117. X\fIAddr\fP
  1118. XThe virtual address of the associated \fBstruct tty\fP in \fB/dev/kmem\fP.
  1119. X.TP
  1120. X\fIRawq\fP
  1121. X.br
  1122. X.ns
  1123. X.TP
  1124. X\fICanq\fP
  1125. X.br
  1126. X.ns
  1127. X.TP
  1128. X\fIOutq\fP
  1129. XThe number of characters in the terminal I/O queues.
  1130. XThese refer to the raw input queue, the canonical input queue
  1131. Xand the output queue.
  1132. X.TP
  1133. X\fIPgrp\fP
  1134. XThe process group associated with the terminal.
  1135. X.PP
  1136. XAfter listing the requested output, \fIsps\fP prints a summary line.
  1137. XThis indicates the number and total virtual memory size of all processes,
  1138. Xthe number and total virtual size of busy processes,
  1139. Xthe number and real memory size of loaded processes
  1140. Xand the number and real size of swapped processes.
  1141. X.SH DIAGNOSTICS
  1142. X\fISps\fP reports a self-explanatory message if it is given an
  1143. Xinvalid argument list.
  1144. XThe program also complains if it cannot find necessary system information.
  1145. X.PP
  1146. XAt initialisation, \fIsps\fP complains if it cannot find the addresses of
  1147. Xrequisite system structures in the kernel symbol file.
  1148. XThis is usually the case because the system is rarely configured to support
  1149. Xall known devices.
  1150. X\fISps\fP also complains if more than one user shares the same user-id
  1151. Xin the password file (\fB/etc/passwd\fP).
  1152. X.SH EXAMPLES
  1153. X\fBsps vb\fP
  1154. X.PP
  1155. X\fISps\fP describes all busy processes in a verbose manner.
  1156. X.PP
  1157. X\fBsps dtg 9 h1 co\fP
  1158. X.PP
  1159. X\fISps\fP lists processes associated with terminals \fB9\fP,
  1160. X\fBh1\fP and the \fBconsole\fP.
  1161. XThe output reflects the disc activity caused by these processes.
  1162. XThe process group of each process is also included in the output.
  1163. X.PP
  1164. X\fBsps weu robert fred \-r 2\fP
  1165. X.PP
  1166. X\fISps\fP reports processes belonging to the specified users.
  1167. XIt lists the environment as well as all the command arguments in a wide format.
  1168. XThe output is produced indefinitely, with a delay of two seconds between
  1169. Xeach listing.
  1170. X.PP
  1171. X\fBsps is /vmunix.new\fP
  1172. X.PP
  1173. X\fISps\fP is initialised. It reads its symbol information from the
  1174. Xspecified file.
  1175. X.SH FILES
  1176. X.ta 2.5i
  1177. X.nf
  1178. X\fB/dev/console\fP    Console
  1179. X\fB/dev/tty??\fP    Terminal and pty devices
  1180. X\fB/dev/kmem\fP    Kernel virtual memory
  1181. X\fB/dev/mem\fP    Physical memory
  1182. X\fB/dev/drum\fP    Paging and swap device
  1183. X\fB/etc/passwd\fP    Password file
  1184. X\fB/etc/spsinfo\fP    Information file
  1185. X\fB/vmunix\fP    Symbol file of \fB/dev/kmem\fP addresses
  1186. X\fB/etc/termcap\fP    To determine the output terminal width
  1187. X.fi
  1188. X.ta
  1189. X.SH SEE ALSO
  1190. X\fIiostat\fP(1), \fIkill\fP(1), \fIps\fP(1),
  1191. X\fIvmstat\fP(1), \fIexec\fP(2),
  1192. X\fIflock\fP(2), \fInice\fP(2), \fIpause\fP(2), \fIselect\fP(2), \fIsetuid\fP(2),
  1193. X\fIsigvec\fP(2), \fIvadvise\fP(2), \fIvfork\fP(2), \fIwait\fP(2),
  1194. X\fIpty\fP(4),\fItty\fP(4), \fIpstat\fP(8).
  1195. X.SH AUTHORS
  1196. XSeveral. In particular, J. E. Kulp and J. Robert Ward,
  1197. X\fB<robert@olsen.uucp>\fP.
  1198. X.LP
  1199. XNFS changes incorporated by Alexander Dupuy,
  1200. X\fB<dupuy@amsterdam.columbia.edu>\fP
  1201. X.LP
  1202. XSunOS 4.0 implementation by Alexander Dupuy and
  1203. XCharlie Kim \fB<cck@cunixc.cc.columbia.edu>\fP.
  1204. X.LP
  1205. XUltrix 2.\fIx\fP additions incorporated by Rob Lehman at CUUCA.
  1206. X.LP
  1207. XSunOS 4.1 additions incorporated by Sakari Jalovaara, \fB<sja@sirius.hut.fi>\fP.
  1208. X.LP
  1209. XCurrently maintained by J. Robert Ward, \fB<robert@olsen.uu.ch>\fP
  1210. X.SH BUGS
  1211. XBecause the system is continually changing, the information reported by
  1212. X\fIsps\fP is only an approximation to reality.
  1213. XIf invoked by root, \fIsps\fP renices itself to \-20 in an attempt to run as
  1214. Xfast as possible.
  1215. X.PP
  1216. X\fISps\fP recognises the sizes and addresses of internal kernel
  1217. Xtables whenever it is invoked. However, it must be recompiled
  1218. Xif major modifications are made to the kernel.
  1219. X.PP
  1220. X\fISps\fP does not list all the detailed information shown by \fIps\fP(1).
  1221. XNor are all the options supported by \fIps\fP(1) available from \fIsps\fP.
  1222. X.PP
  1223. X\fISps\fP does not understand all the possible
  1224. Xreasons why a process may be sleeping.
  1225. X.PP
  1226. XThe code of \fIsps\fP is inherently machine-dependent and non-portable.
  1227. X.PP
  1228. XThe number of options to \fIsps\fP is ridiculous.
  1229. END_OF_FILE
  1230.   if test 15259 -ne `wc -c <'sps.l'`; then
  1231.     echo shar: \"'sps.l'\" unpacked with wrong size!
  1232.   fi
  1233.   # end of 'sps.l'
  1234. fi
  1235. if test -f 'ttystatus.c' -a "${1}" != "-c" ; then 
  1236.   echo shar: Will not clobber existing file \"'ttystatus.c'\"
  1237. else
  1238.   echo shar: Extracting \"'ttystatus.c'\" \(3826 characters\)
  1239.   sed "s/^X//" >'ttystatus.c' <<'END_OF_FILE'
  1240. X# ifndef lint
  1241. Xstatic char SccsId[] =  "@(#)ttystatus.c    1.1\t10/1/88" ;
  1242. X# endif
  1243. X
  1244. X# include       "sps.h"
  1245. X# include       "flags.h"
  1246. X# include       <stdio.h>
  1247. X# include       <h/ioctl.h>
  1248. X# ifdef SUNOS40
  1249. X# include       <h/stream.h>
  1250. X# else
  1251. X# include       <h/tty.h>
  1252. X# endif
  1253. X# ifdef CHAOS
  1254. X# include       <chunix/chsys.h>
  1255. X# include       <chaos/chaos.h>
  1256. X# endif
  1257. X
  1258. X/*
  1259. X** TTYSTATUS - Reads the kernel memory for tty structures of active processes.
  1260. X** The addresses of the associated struct ttys of /dev/kmem are kept in the
  1261. X** info structure. Here we use those addresses to access the structures.
  1262. X** Actually, we are mostly interested just in the process group of each tty.
  1263. X*/
  1264. Xttystatus ()
  1265. X{
  1266. X    register struct ttyline *lp ;
  1267. X# ifdef SUNOS40
  1268. X    struct stdata           *stdata ;
  1269. X    extern struct stdata    *getstdata() ;
  1270. X# else
  1271. X    struct tty              tty ;
  1272. X# endif
  1273. X    extern struct flags     Flg ;
  1274. X    extern struct info      Info ;
  1275. X# ifndef KVM
  1276. X    extern int              Flkmem ;
  1277. X# endif
  1278. X
  1279. X# ifdef SUNOS40
  1280. X    if ( !init_streams_tab() )
  1281. X        fprintf( stderr, "can't read streams table\n" ) ;
  1282. X# endif
  1283. X
  1284. X    if ( Flg.flg_y )
  1285. X# ifdef SUNOS40
  1286. X        printf( "Ty   Dev       Addr  Pgrp\n" ) ;
  1287. X# else
  1288. X        printf( "Ty   Dev       Addr Rawq Canq Outq  Pgrp\n" ) ;
  1289. X# endif
  1290. X    lp = Info.i_ttyline ;
  1291. X# ifdef CHAOS
  1292. X    while ( lp->l_name[0] && lp->l_name[0] != 'C' )
  1293. X# else
  1294. X    while ( lp->l_name[0] )
  1295. X# endif
  1296. X    {
  1297. X# ifdef SUNOS40 
  1298. X        if ( stdata = getstdata ( lp->l_addr, lp->l_dev ) )
  1299. X        {
  1300. X            lp->l_stdata = stdata ;
  1301. X            lp->l_pgrp = stdata->sd_pgrp ;
  1302. X            prstr( lp, stdata ) ;
  1303. X        }
  1304. X        else
  1305. X            lp->l_pgrp = 0 ;
  1306. X        lp++ ;
  1307. X# else
  1308. X        if ( getkmem( (long)lp->l_addr, (char*)&tty, sizeof( tty ) )
  1309. X        != sizeof( struct tty ) )
  1310. X        {
  1311. X            fprintf( stderr,
  1312. X                "sps - Can't read struct tty for tty%.2s\n",
  1313. X                lp->l_name ) ;
  1314. X            lp->l_pgrp = 0 ;
  1315. X            lp++ ;
  1316. X            continue ;
  1317. X        }
  1318. X        lp->l_pgrp = tty.t_pgrp ;
  1319. X        prtty( lp, &tty ) ;
  1320. X        lp++ ;
  1321. X# endif
  1322. X    }
  1323. X# ifdef CHAOS
  1324. X    chaosttys( lp ) ;               
  1325. X# endif
  1326. X}
  1327. X
  1328. X# ifdef SUNOS40
  1329. X
  1330. X/* PRSTR - Print out the stdata structure */
  1331. Xprstr ( lp, stdata )
  1332. X
  1333. Xregister struct ttyline         *lp ;
  1334. Xregister struct stdata          *stdata ;
  1335. X
  1336. X{
  1337. X    extern struct flags     Flg ;
  1338. X
  1339. X    if ( !Flg.flg_y )
  1340. X        return ;
  1341. X    printf( "%-2.2s %2d,%2d 0x%08x %5d\n",
  1342. X        lp->l_name,
  1343. X        major( lp->l_dev ),
  1344. X        minor( lp->l_dev ),
  1345. X        lp->l_addr,
  1346. X        stdata->sd_pgrp ) ;
  1347. X}
  1348. X
  1349. X# else
  1350. X
  1351. X/* PRTTY - Print out the tty structure */
  1352. Xprtty ( lp, tty )
  1353. X
  1354. Xregister struct ttyline         *lp ;
  1355. Xregister struct tty             *tty ;
  1356. X
  1357. X{
  1358. X    extern struct flags     Flg ;
  1359. X
  1360. X    if ( !Flg.flg_y )
  1361. X        return ;
  1362. X    printf( "%-2.2s %2d,%2d 0x%08x %4d %4d %4d %5d\n",
  1363. X        lp->l_name,
  1364. X        major( lp->l_dev ),
  1365. X        minor( lp->l_dev ),
  1366. X        lp->l_addr,
  1367. X        tty->t_rawq.c_cc,
  1368. X        tty->t_canq.c_cc,
  1369. X        tty->t_outq.c_cc,
  1370. X        tty->t_pgrp ) ;
  1371. X}
  1372. X
  1373. X# endif
  1374. X
  1375. X# ifdef CHAOS
  1376. X
  1377. X/* CHAOSTTYS - Finds ttys attached to the Chaos net */
  1378. Xchaosttys ( lp )
  1379. X
  1380. Xregister struct ttyline         *lp ;
  1381. X
  1382. X{
  1383. X    register struct connection      **cnp ;
  1384. X    register int                    i ;
  1385. X    struct tty                      tty ;
  1386. X    struct connection               *conntab[CHNCONNS] ;
  1387. X    struct connection               conn ;
  1388. X    extern struct info              Info ;
  1389. X    extern int                      Flkmem ;
  1390. X
  1391. X    (void)getkmem( (long)Info.i_Chconntab, (char*)conntab,
  1392. X        sizeof( conntab ) ) ;
  1393. X    for ( i = 0, cnp = conntab ; cnp < &conntab[CHNCONNS] ; i++, cnp++ )
  1394. X    {
  1395. X        if ( !*cnp )
  1396. X            continue ;
  1397. X        (void)getkmem( (long)*cnp, (char*)&conn, sizeof( conn ) ) ;
  1398. X        if ( !(conn.cn_flags & CHTTY) )
  1399. X            continue ;
  1400. X        (void)getkmem( (long)conn.cn_ttyp, (char*)&tty, sizeof( tty ) ) ;
  1401. X        if ( lp >= &Info.i_ttyline[MAXTTYS] )
  1402. X            prexit( "sps - Too many chaos ttys\n" ) ;
  1403. X        lp->l_addr = conn.cn_ttyp ;
  1404. X        lp->l_pgrp = tty.t_pgrp ;
  1405. X        lp->l_dev = tty.t_dev ;
  1406. X        lp->l_name[0] = 'C' ;
  1407. X        lp->l_name[1] = i < 10 ? '0'+i : i-10 <= 'z'-'a' ? i-10+'a' :
  1408. X                i-10-('z'-'a')+'A' ;
  1409. X        prtty( lp, &tty ) ;
  1410. X        lp++ ;
  1411. X    }
  1412. X}
  1413. X
  1414. X# endif
  1415. END_OF_FILE
  1416.   if test 3826 -ne `wc -c <'ttystatus.c'`; then
  1417.     echo shar: \"'ttystatus.c'\" unpacked with wrong size!
  1418.   fi
  1419.   # end of 'ttystatus.c'
  1420. fi
  1421. if test -f 'waitingfor.c' -a "${1}" != "-c" ; then 
  1422.   echo shar: Will not clobber existing file \"'waitingfor.c'\"
  1423. else
  1424.   echo shar: Extracting \"'waitingfor.c'\" \(9904 characters\)
  1425.   sed "s/^X//" >'waitingfor.c' <<'END_OF_FILE'
  1426. X# ifndef lint
  1427. Xstatic char SccsId[] =  "@(#)waitingfor.c    1.5\t8/6/90" ;
  1428. X# endif
  1429. X
  1430. X# include        "sps.h"
  1431. X# ifndef SUNOS40
  1432. X# include        <h/text.h>
  1433. X# endif SUNOS40
  1434. X
  1435. X# ifdef NFS
  1436. X#  ifdef DEC3100
  1437. X#   include        <h/gnode.h>
  1438. X#   include        <h/inode.h>
  1439. X#  else DEC3100
  1440. X#   include        <h/vnode.h>
  1441. X#   include        <ufs/inode.h>
  1442. X# endif DEC3100
  1443. X# else
  1444. X#  include        <h/inode.h>
  1445. X# endif NFS
  1446. X
  1447. X# include        <h/ioctl.h>
  1448. X# ifdef SUNOS40
  1449. X#  include        <h/stream.h>
  1450. X#  include        <h/tty.h>
  1451. X#  include        <h/ptyvar.h>
  1452. X# else SUNOS40
  1453. X#  include        <h/tty.h>
  1454. X# endif SUNOS40
  1455. X
  1456. X# include        <h/buf.h>
  1457. X# ifdef BSD42
  1458. X#  ifdef NFS
  1459. X#   ifndef NOQUOTA
  1460. X#    ifdef DEC3100
  1461. X#     include        <h/quota.h>
  1462. X#    else
  1463. X#     include        <ufs/quota.h>
  1464. X#    endif DEC3100
  1465. X#   endif NOQUOTA
  1466. X#  else NFS
  1467. X#   include        <h/quota.h>
  1468. X#  endif NFS
  1469. X# include        <h/mbuf.h>
  1470. X# include        <h/socket.h>
  1471. X# include        <h/socketvar.h>
  1472. X# endif BSD42
  1473. X
  1474. X/* 1 if `w' is in the address range defined by `a1' and `a2' ... */
  1475. X# define        INRANGE( w, a1, a2 ) \
  1476. X            ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
  1477. X
  1478. X/* NFS changes incorporated by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
  1479. X
  1480. X/* WAITINGFOR - Determine what a process is waiting for and describe it. */
  1481. Xchar    *waitingfor ( p )
  1482. X
  1483. Xstruct process                  *p ;
  1484. X
  1485. X{
  1486. X    register caddr_t        w ;
  1487. X    register struct ttyline *lp ;
  1488. X    register struct symbol  *s ;
  1489. X    register char           *cp ;
  1490. X# ifdef BSD42
  1491. X    struct socket           sc ;
  1492. X# endif
  1493. X    int            rc ;
  1494. X    static char             wbuf[ 8 ] ;
  1495. X    extern struct info      Info ;
  1496. X    extern struct symbol    Symbollist[] ;
  1497. X    char                    *sprintf() ;
  1498. X# ifdef SUNOS40
  1499. X    char                    *gettty() ;
  1500. X# endif
  1501. X
  1502. X    w = p->pr_p.p_wchan ;
  1503. X    if ( !w )
  1504. X        return ( "null" ) ;
  1505. X    /* Waiting for a child process, alternatively in a vfork() ? */
  1506. X    if ( INRANGE( w, Info.i_proc0, &Info.i_proc0[ Info.i_nproc ] ) )
  1507. X        return ( p->pr_p.p_flag & SNOVM ? "vfork" : "child" ) ;
  1508. X# ifndef SUNOS40
  1509. X    /* Waiting for a page to be brought in ? */
  1510. X    if ( INRANGE( w, Info.i_swbuf0, &Info.i_swbuf0[ Info.i_nswbuf ] ) )
  1511. X        return ( "swap" ) ;
  1512. X    /* Waiting for discio through a block device to complete ? */
  1513. X    if ( INRANGE( w, Info.i_buf0, &Info.i_buf0[ Info.i_nbuf ] ) )
  1514. X        /* SHOULD ACTUALLY READ AS "blkio" BUT "discio" IS WHAT
  1515. X           IS GENERALLY MEANT HERE. */
  1516. X        return ( "discio" ) ;
  1517. X    /* Waiting for a text page to be brought in ? */
  1518. X    if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) )
  1519. X        return ( "swtext" ) ;
  1520. X# endif SUNOS40
  1521. X
  1522. X# ifdef BSD42
  1523. X#  ifndef NOQUOTA
  1524. X    /* Waiting for an event associated with the quota system ? */
  1525. X    if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) )
  1526. X        return ( "quota" ) ;
  1527. X#  endif NOQUOTA
  1528. X# endif BSD42
  1529. X
  1530. X# ifndef SUNOS41
  1531. X         /* Sorry, I don't know how to do this...
  1532. X          * I kinda think that SunOS 4.1 allocates inode
  1533. X          * buffer entries dynamically.  Maybe it could be
  1534. X          * possible to read in all "struct file"s and
  1535. X          * compare each file.f_data to the wait channel.    ++sja
  1536. X          */
  1537. X    /* Waiting for an inode ? */
  1538. X    if ( INRANGE( w, Info.i_inode0, &Info.i_inode0[ Info.i_ninode ] ) )
  1539. X#  ifdef ULTRIX20
  1540. X        switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct gnode ))
  1541. X#  else
  1542. X        switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct inode ))
  1543. X#  endif ULTRIX20
  1544. X        {
  1545. X#  ifdef BSD42
  1546. X#   ifdef NFS
  1547. X            case (int)&((struct inode*)0)->i_vnode.v_exlockc :
  1548. X                /* Exclusive lock on this inode */
  1549. X                return ( "exlock" ) ;
  1550. X            case (int)&((struct inode*)0)->i_vnode.v_shlockc :
  1551. X                /* Shared lock on this inode */
  1552. X                return ( "shlock" ) ;
  1553. X#   else NFS
  1554. X#    ifdef ULTRIX20
  1555. X#     ifndef DEC3100
  1556. X            /* Compile this code with gcc if you want to run it
  1557. X               properly.  The DEC compiler can't handle this. */
  1558. X            case (int)&((struct gnode*)0)->g_exlockc :
  1559. X                /* Exclusive lock on this inode */
  1560. X                return ( "exlock" ) ;
  1561. X            case (int)&((struct gnode*)0)->g_shlockc :
  1562. X                /* Shared lock on this inode */
  1563. X                return ( "shlock" ) ;
  1564. X            case (int)&((struct gnode*)0)->g_frcnt :
  1565. X                /* Open fifo with no readers */
  1566. X                return ( "wfifo" ) ;
  1567. X            case (int)&((struct gnode*)0)->g_fwcnt :
  1568. X                /* Open fifo with no writers */
  1569. X                return ( "rfifo" ) ;
  1570. X#     endif DEC3100
  1571. X#    else ULTRIX20
  1572. X            case (int)&((struct inode*)0)->i_exlockc :
  1573. X                /* Exclusive lock on this inode */
  1574. X                return ( "exlock" ) ;
  1575. X            case (int)&((struct inode*)0)->i_shlockc :
  1576. X                /* Shared lock on this inode */
  1577. X                return ( "shlock" ) ;
  1578. X#    endif ULTRIX20
  1579. X#   endif NFS
  1580. X#  else BSD42 
  1581. X            case 1 :
  1582. X                return ( "wpipe" ) ;
  1583. X            case 2 :
  1584. X                return ( "rpipe" ) ;
  1585. X            case (int)&((struct inode*)0)->i_un.i_group.g_datq :
  1586. X                return ( "rmux" ) ;
  1587. X#  endif BSD42
  1588. X            default :
  1589. X                /* Inode probably locked */
  1590. X                return ( "inode" ) ;
  1591. X        }
  1592. X# endif SUNOS41
  1593. X
  1594. X# if defined(BSD42) && (defined(SUNOS40) || defined(NMBCLUSTERS))
  1595. X    /* Waiting for a structure inside an mbuf ? If so, try to find why */
  1596. X#  ifdef SUNOS40
  1597. X    if ( INRANGE( w, Info.i_mbutl,
  1598. X    &Info.i_mbutl[ MBPOOLBYTES / sizeof( struct mbuf ) ] ) )
  1599. X#  else
  1600. X    if ( INRANGE( w, Info.i_mbutl,
  1601. X    &Info.i_mbutl[ NMBCLUSTERS * CLBYTES / sizeof( struct mbuf ) ] ) )
  1602. X#  endif SUNOS40
  1603. X        switch ( ((int)w - (int)Info.i_mbutl) % sizeof( struct mbuf )
  1604. X            - (int)&((struct mbuf*)0)->m_dat[0] )
  1605. X        {
  1606. X            case (int)&((struct socket*)0)->so_timeo :
  1607. X                /* Socket timeout event - Guess why */
  1608. X                rc = getsocket( (struct socket*)(w
  1609. X                    - (int)&((struct socket*)0)->so_timeo),
  1610. X                        &sc ) ;
  1611. X                return ( rc && (sc.so_state & SS_ISCONNECTING)
  1612. X                    ? "connct" 
  1613. X                    : rc && ((sc.so_options & SO_ACCEPTCONN)
  1614. X                      && !sc.so_qlen)
  1615. X                    ? "accept" : "socket" ) ;
  1616. X            case (int)&((struct socket*)0)->so_rcv.sb_cc :
  1617. X                /* Read from an empty socket. Here we actually
  1618. X                   attempt to determine whether the socket
  1619. X                   structure in question really does refer to
  1620. X                   a socket, or whether it is in fact a pipe
  1621. X                   in disguise. */
  1622. X                return ( getsocket( (struct socket*)(w
  1623. X                    - (int)&((struct socket*)0)->so_rcv.sb_cc),
  1624. X                        &sc )
  1625. X                    && sc.so_type == SOCK_STREAM
  1626. X#  ifdef BSD43
  1627. X                    && ((sc.so_state
  1628. X                        & (SS_ISCONNECTED|SS_CANTSENDMORE))
  1629. X                        == (SS_ISCONNECTED|SS_CANTSENDMORE))
  1630. X#  else
  1631. X                    && !sc.so_rcv.sb_hiwat
  1632. X                    && !sc.so_rcv.sb_mbmax
  1633. X                    && (sc.so_state
  1634. X                        & (SS_ISCONNECTED|SS_CANTRCVMORE))
  1635. X#  endif BSD43
  1636. X                    ? "rpipe" : "rsockt" ) ;
  1637. X            case (int)&((struct socket*)0)->so_snd.sb_cc :
  1638. X                /* Write to a full socket. Again, we try
  1639. X                   to determine whether or not this is a
  1640. X                   real socket or a pipe. */
  1641. X                return ( getsocket( (struct socket*)(w
  1642. X                    - (int)&((struct socket*)0)->so_snd.sb_cc),
  1643. X                        &sc )
  1644. X#  ifdef BSD43
  1645. X                    && sc.so_type == SOCK_STREAM
  1646. X                    && ((sc.so_state
  1647. X                        & (SS_ISCONNECTED|SS_CANTRCVMORE))
  1648. X                        == (SS_ISCONNECTED|SS_CANTRCVMORE))
  1649. X#  else
  1650. X                    && sc.so_rcv.sb_hiwat == 2048
  1651. X                    && sc.so_rcv.sb_mbmax == 4096
  1652. X                    && (sc.so_state
  1653. X                        & (SS_ISCONNECTED|SS_CANTSENDMORE))
  1654. X#  endif BSD43
  1655. X                    ? "wpipe" : "wsockt" ) ;
  1656. X            default :
  1657. X                /* Other mbuf event */
  1658. X                return ( "mbuf" ) ;
  1659. X        }
  1660. X# endif BSD42
  1661. X
  1662. X# ifdef SUNOS41
  1663. X    if  ( w == (caddr_t)p->pr_p.p_uarea )
  1664. X        return ( "pause" ) ;
  1665. X# endif SUNOS41
  1666. X    /* Look in the symbol table for known wait addresses. */
  1667. X    for ( s = Symbollist ; s->s_kname ; s++ )
  1668. X        if ( s->s_wait && w == *s->s_info )
  1669. X            return ( s->s_wait ) ;
  1670. X
  1671. X# ifdef SUNOS40
  1672. X    /* Have to check for ptys in a funny sort of way */
  1673. X    if ( INRANGE( w, Info.i_ptybase, &Info.i_ptybase[ Info.i_npty ] ) )
  1674. X    {
  1675. X        switch ( ((int)w - (int)Info.i_ptybase) % sizeof( struct pty ) )
  1676. X        {
  1677. X            case (int)&((struct pty*)0)->pt_flags :
  1678. X                cp = "opty??" ;
  1679. X                break ;
  1680. X            case (int)&((struct pty*)0)->pt_ttycommon.t_writeq :
  1681. X                cp = "spty??" ;
  1682. X                break ;
  1683. X            default :
  1684. X                cp = "?pty??" ;
  1685. X        }
  1686. X        /* by the conventional naming, anyhow */
  1687. X        cp[4] = 'p' + (((int)w - (int)Info.i_ptybase)
  1688. X            / sizeof( struct pty )) / 16 ;
  1689. X        if ( ( cp[5] = '0' + (((int) w - (int)Info.i_ptybase)
  1690. X            / sizeof( struct pty )) % 16 ) > '9' )
  1691. X            cp[5] += 'a' - '9' - 1 ;
  1692. X        return( cp ) ;
  1693. X    }
  1694. X    /* Check for ttys last, since there may be a lot of them. */
  1695. X    if ( p->pr_tty != 0 )
  1696. X        if ( cp = gettty( p->pr_tty, w ) )
  1697. X            return( cp ) ;
  1698. X    for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  1699. X        if ( cp = gettty( lp, w ) )
  1700. X            return( cp ) ;
  1701. X# else SUNOS40
  1702. X    /* Waiting for tty I/O ? If so, find which tty it is */
  1703. X    for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  1704. X        if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) )
  1705. X        {
  1706. X#  ifdef DEC3100
  1707. X            /* Cretinous DEC compiler can't handle case
  1708. X               constructs like the following ... */
  1709. X            cp = "?tty??" ;
  1710. X#  else DEC3100
  1711. X            switch ( (int)w - (int)lp->l_addr )
  1712. X            {
  1713. X                case (int)&((struct tty*)0)->t_rawq :
  1714. X                    /* Read from a tty or slave pty */
  1715. X                    cp = "rtty??" ;
  1716. X                    break ;
  1717. X                case (int)&((struct tty*)0)->t_outq :
  1718. X                    /* Write to a tty or slave pty */
  1719. X                    cp = "wtty??" ;
  1720. X                    break ;
  1721. X                case (int)&((struct tty*)0)->t_canq :
  1722. X                    /* Waiting for icon to be opened */
  1723. X                    cp = "itty??" ;
  1724. X                    break ;
  1725. X                case (int)&((struct tty*)0)->t_state :
  1726. X                    /* Tty not open */
  1727. X                    cp = "otty??" ;
  1728. X                    break ;
  1729. X                case (int)&((struct tty*)0)->t_outq.c_cf :
  1730. X                    /* Read from a controller pty */
  1731. X                    cp = "rpty??" ;
  1732. X                    break ;
  1733. X                case (int)&((struct tty*)0)->t_rawq.c_cf :
  1734. X                    /* Write to a controller pty */
  1735. X                    cp = "wpty??" ;
  1736. X                    break ;
  1737. X                default :
  1738. X                    cp = "?tty??" ;
  1739. X                    break ;
  1740. X            }
  1741. X#  endif DEC3100
  1742. X            cp[4] = lp->l_name[0] ;
  1743. X            cp[5] = lp->l_name[1] ;
  1744. X            return ( cp ) ;
  1745. X        }
  1746. X# endif SUNOS40
  1747. X
  1748. X    /* No reason for the wait state has been found.
  1749. X       Return the wait channel as a hexadecimal address. */
  1750. X# ifdef SUN
  1751. X    (void)sprintf( wbuf, "x%05x", w - KERNELBASE ) ;
  1752. X# else
  1753. X    (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ;
  1754. X# endif
  1755. X    return ( wbuf ) ;
  1756. X}
  1757. X
  1758. X
  1759. X# ifdef BSD42
  1760. X/*
  1761. X** GETSOCKET - Reads a `struct socket' from the kernel virtual memory address
  1762. X** identified by `ks' into the buffer `s'.
  1763. X*/
  1764. Xgetsocket ( ks, s )
  1765. X
  1766. Xstruct socket                   *ks ;
  1767. Xstruct socket                   *s ;
  1768. X
  1769. X{
  1770. X    return ( getkmem( (long)ks, (char*)s, sizeof( struct socket ) )
  1771. X        == sizeof( struct socket ) ) ;
  1772. X}
  1773. X# endif BSD42
  1774. END_OF_FILE
  1775.   if test 9904 -ne `wc -c <'waitingfor.c'`; then
  1776.     echo shar: \"'waitingfor.c'\" unpacked with wrong size!
  1777.   fi
  1778.   # end of 'waitingfor.c'
  1779. fi
  1780. echo shar: End of archive 1 \(of 4\).
  1781. cp /dev/null ark1isdone
  1782. MISSING=""
  1783. for I in 1 2 3 4 ; do
  1784.     if test ! -f ark${I}isdone ; then
  1785.     MISSING="${MISSING} ${I}"
  1786.     fi
  1787. done
  1788. if test "${MISSING}" = "" ; then
  1789.     echo You have unpacked all 4 archives.
  1790.     rm -f ark[1-9]isdone
  1791. else
  1792.     echo You still must unpack the following archives:
  1793.     echo "        " ${MISSING}
  1794. fi
  1795. exit 0
  1796. exit 0 # Just in case...
  1797.